﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows.Forms;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.LIB;
using YArchitech.ProgressBar;
using YArchitech.Revit;
using HYCodeBase.WinForm;
using HYLightingEquipmentLay;
using LightingEquipmentLay.Utility;

namespace LightingEquipmentLay.RegionSearch
{
	internal class LightingLayoutOper
	{
		public static bool InitLaneLightStyle()
		{
			LightCfgData configData = Common.GetConfigData();
			LightingLayoutOper.m_nBeamCellCount = ushort.Parse(configData.m_nBeamLightNums.ToString());
			LightingLayoutOper.m_nFlatPlateFloorCount = ushort.Parse(configData.m_nGridLightNums.ToString());
			return true;
		}

		public static List<KeyValuePair<LightingLayoutOper.ComparableLine, List<XYZ>>> GetLineIntersectionInfos(List<Line> lstLaneCvs)
		{
			List<LightingLayoutOper.ComparableLine> lstCmpLanes = new List<LightingLayoutOper.ComparableLine>();
			lstLaneCvs.ForEach(delegate(Line l)
			{
				lstCmpLanes.Add(new LightingLayoutOper.ComparableLine(l));
			});
			Dictionary<LightingLayoutOper.ComparableLine, List<XYZ>> dictionary = new Dictionary<LightingLayoutOper.ComparableLine, List<XYZ>>();
			int count = lstLaneCvs.Count;
			for (int i = 0; i < count; i++)
			{
				LightingLayoutOper.ComparableLine comparableLine = lstCmpLanes[i];
				List<XYZ> list = new List<XYZ>();
				for (int j = i + 1; j < count; j++)
				{
					LightingLayoutOper.ComparableLine comparableLine2 = lstCmpLanes[j];
					IntersectionResultArray intersectionResultArray = null;
					if ((int)comparableLine.GeLine.Intersect(comparableLine2.GeLine, out intersectionResultArray) == 8 && intersectionResultArray != null)
					{
						List<XYZ> list2 = new List<XYZ>();
						list2.AddRange(from IntersectionResult e in intersectionResultArray
						select e.XYZPoint);
						if (dictionary.ContainsKey(comparableLine2))
						{
							dictionary[comparableLine2].AddRange(list2);
						}
						else
						{
							dictionary.Add(comparableLine2, list2);
						}
						list.AddRange(list2);
					}
				}
				if (dictionary.ContainsKey(comparableLine))
				{
					dictionary[comparableLine].AddRange(list);
				}
				else
				{
					dictionary.Add(comparableLine, list);
				}
			}
			Dictionary<LightingLayoutOper.ComparableLine, List<XYZ>> dictionary2 = new Dictionary<LightingLayoutOper.ComparableLine, List<XYZ>>();
			foreach (KeyValuePair<LightingLayoutOper.ComparableLine, List<XYZ>> keyValuePair in dictionary)
			{
				List<XYZ> value = new List<XYZ>(keyValuePair.Value.Distinct(new LightingLayoutOper.XyzEqualityComparer(1E-06)));
				dictionary2.Add(keyValuePair.Key, value);
			}
			return (from p in dictionary2
			orderby p.Value.Count descending
			select p).ToList<KeyValuePair<LightingLayoutOper.ComparableLine, List<XYZ>>>();
		}

		public static List<LightingLayoutOper.LightingInfo> CalcLaneLightingPos(Level level, RegionFuncInfo BeamRegion, Line geLane, bool bBeamCell)
		{
			List<LightingLayoutOper.LightingInfo> result = new List<LightingLayoutOper.LightingInfo>();
			List<XYZ> laneBeamCellInterPts = LightingLayoutOper.GetLaneBeamCellInterPts(level, BeamRegion, geLane, false);
			int count = laneBeamCellInterPts.Count;
			if (count != 1)
			{
				if (count == 2)
				{
					result = LightingLayoutOper.CalcLaneLightingPos(laneBeamCellInterPts[0], laneBeamCellInterPts[1], bBeamCell);
				}
			}
			else
			{
				List<XYZ> laneBeamCellInterPts2 = LightingLayoutOper.GetLaneBeamCellInterPts(level, BeamRegion, geLane, true);
				if (laneBeamCellInterPts2.Count == 2)
				{
					result = LightingLayoutOper.CalcLaneLightingPos(laneBeamCellInterPts2[0], laneBeamCellInterPts2[1], bBeamCell);
				}
			}
			return result;
		}

		private static List<XYZ> GetLaneBeamCellInterPts(Level level, RegionFuncInfo BeamRegion, Line geLane, bool bMakeUnbound = false)
		{
			Plane plane = RegionSearchManager.CreatePlaneByLevel(level);
			Curve projectSegCurve = Common.GetProjectSegCurve(plane, geLane);
			if (bMakeUnbound)
			{
				projectSegCurve.MakeUnbound();
			}
			List<XYZ> list = new List<XYZ>();
			foreach (object obj in BeamRegion.BoundaryCvs)
			{
				Line line = ((Curve)obj) as Line;
				if (!(line == null))
				{
					Curve projectSegCurve2 = Common.GetProjectSegCurve(plane, line);
					IntersectionResultArray intersectionResultArray = null;
					if ((int)projectSegCurve2.Intersect(projectSegCurve, out intersectionResultArray) == 8 && intersectionResultArray != null && intersectionResultArray.Size > 0)
					{
						list.AddRange(from IntersectionResult e in intersectionResultArray
						select e.XYZPoint);
					}
				}
			}
			return list;
		}

		public static List<LightingLayoutOper.LightingInfo> CalcLaneLightingPos(XYZ ptS, XYZ ptE, bool bBeamCell)
		{
			ushort nCount = LightingLayoutOper.CalcLightingCounts(ptS.DistanceTo(ptE), bBeamCell);
			return LightingLayoutOper.CalcLineLightingPosByCount(ptS, ptE, nCount, false);
		}

		private static List<LightingLayoutOper.LightingInfo> CalcLineLightingPosByCount(XYZ ptS, XYZ ptE, ushort nCount, bool bl = false)
		{
			List<LightingLayoutOper.LightingInfo> list = new List<LightingLayoutOper.LightingInfo>();
			if (nCount > 0)
			{
				if (bl)
				{
					LightingLayoutOper.m_strLightLayStyle = "双";
				}
				if (LightingLayoutOper.m_strLightLayStyle == "双")
				{
					nCount /= 2;
				}
				double num = ptS.DistanceTo(ptE);
				double num2 = num / (double)nCount;
				Line line = Line.CreateBound(ptS, ptE);
				double endParameter = line.GetEndParameter(0);
				double num3 = num2 / 2.0;
				XYZ xyz = ptE.Subtract(ptS).CrossProduct(new XYZ(0.0, 0.0, 1.0)).Normalize();
				if (bl)
				{
					xyz = (ptE - ptS).Normalize();
				}
				XYZ xyz2 = (ptS - ptE).Normalize();
				XYZ xyz3 = new XYZ(1.0, 0.0, 0.0);
				for (int i = 0; i < (int)nCount; i++)
				{
					if (LightingLayoutOper.m_strLightLayStyle == "单")
					{
						XYZ xyz4 = line.Evaluate(endParameter + num3, false);
						double dAng = XYZ.BasisX.AngleOnPlaneTo(ptE - ptS, XYZ.BasisZ);
						if (xyz2.IsAlmostEqualTo(xyz3, 0.01))
						{
							dAng = 0.0;
						}
						list.Add(new LightingLayoutOper.LightingInfo(xyz4, dAng));
					}
					else
					{
						XYZ xyz4 = line.Evaluate(endParameter + num3, false);
						XYZ pt = xyz4.Add(-1.0 * xyz * num / 6.0);
						XYZ pt2 = xyz4.Add(xyz * num / 6.0);
						double dAng = XYZ.BasisX.AngleOnPlaneTo(ptE - ptS, XYZ.BasisZ);
						if (xyz2.IsAlmostEqualTo(xyz3, 0.01))
						{
							dAng = 0.0;
						}
						list.Add(new LightingLayoutOper.LightingInfo(pt, dAng));
						list.Add(new LightingLayoutOper.LightingInfo(pt2, dAng));
					}
					num3 += num2;
				}
			}
			return list;
		}

		public static List<LightingLayoutOper.LightingInfo> DoLightingLayoutByLanes(Level level, List<RegionFuncInfo> BeamLaneRegions, List<KeyValuePair<LightingLayoutOper.ComparableLine, List<XYZ>>> lstLaneInfos, bool bBeamCell)
		{
			List<LightingLayoutOper.LightingInfo> lstResult = new List<LightingLayoutOper.LightingInfo>();
			using (ProgressBarForm progressBarForm = new ProgressBarForm(lstLaneInfos.Count, ProgressBarStyle.Blocks, true))
			{
				WindowHandle owner = new WindowHandle(Process.GetCurrentProcess().MainWindowHandle);
				progressBarForm.Text = "正在进行车道线布灯点位计算";
				progressBarForm.ShowInTaskbar = false;
				progressBarForm.Show(owner);
                Action<LightingLayoutOper.LightingInfo> ss9__0 = null;
				foreach (KeyValuePair<LightingLayoutOper.ComparableLine, List<XYZ>> keyValuePair in lstLaneInfos)
				{
					progressBarForm.RefreshProgressBar();
					if (progressBarForm.m_stopTag)
					{
						break;
					}
					Line geLine = keyValuePair.Key.GeLine;
					foreach (RegionFuncInfo regionFuncInfo in BeamLaneRegions)
					{
						if (!regionFuncInfo.IsLayoutCompleted)
						{
							try
							{
								List<LightingLayoutOper.LightingInfo> list = new List<LightingLayoutOper.LightingInfo>();
								list = LightingLayoutOper.CalcLaneLightingPos(level, regionFuncInfo, geLine, bBeamCell);
								if (list.Count != 0)
								{
									regionFuncInfo.IsLayoutCompleted = (list.Count > 0);
									List<LightingLayoutOper.LightingInfo> list2 = list;
									Action<LightingLayoutOper.LightingInfo> action;
									if ((action = ss9__0) == null)
									{
										action = (ss9__0 = delegate(LightingLayoutOper.LightingInfo e)
										{
											lstResult.Add(e);
										});
									}
									list2.ForEach(action);
								}
							}
							catch (Exception ex)
							{
								TaskDialog.Show("tishi", ex.ToString());
							}
						}
					}
				}
			}
			return lstResult;
		}

		public static List<LightingLayoutOper.LightingInfo> DoLightingLayoutByParkings(List<RegionFuncInfo> lstRegionParkings)
		{
			List<LightingLayoutOper.LightingInfo> list = new List<LightingLayoutOper.LightingInfo>();
			using (ProgressBarForm progressBarForm = new ProgressBarForm(lstRegionParkings.Count, ProgressBarStyle.Blocks, true))
			{
				WindowHandle owner = new WindowHandle(Process.GetCurrentProcess().MainWindowHandle);
				progressBarForm.Text = "正在进行车位布灯点位计算";
				progressBarForm.ShowInTaskbar = false;
				progressBarForm.Show(owner);
				foreach (RegionFuncInfo regionFuncInfo in lstRegionParkings)
				{
					progressBarForm.RefreshProgressBar();
					if (progressBarForm.m_stopTag)
					{
						break;
					}
					Plane plane = UnifiedModified.CreatePlane(-XYZ.BasisZ, XYZ.Zero);
					RegionParkingInfo regionParkingInfo = regionFuncInfo as RegionParkingInfo;
					XYZ xyz = regionParkingInfo.GeoPos;
					xyz = Common.ProjectOnto(plane, xyz);
					Line line = Line.CreateUnbound(xyz, regionParkingInfo.Direction);
					List<XYZ> list2 = new List<XYZ>();
					foreach (object obj in regionParkingInfo.BoundaryCvs)
					{
						Curve cv = (Curve)obj;
						Curve projectSegCurve = Common.GetProjectSegCurve(plane, cv);
						IntersectionResultArray intersectionResultArray = null;
						if ((int)line.Intersect(projectSegCurve, out intersectionResultArray) == 8 && intersectionResultArray != null)
						{
							list2.Add(intersectionResultArray.get_Item(0).XYZPoint);
						}
					}
					if (list2.Count == 2)
					{
						XYZ xyz2 = list2.First<XYZ>();
						XYZ xyz3 = list2.Last<XYZ>();
						if ((ushort)(xyz2.DistanceTo(xyz3) / regionParkingInfo.Width) < 4)
						{
							double dAng = XYZ.BasisX.AngleOnPlaneTo(xyz3 - xyz2, XYZ.BasisZ);
							list.Add(new LightingLayoutOper.LightingInfo(xyz, dAng));
						}
						else
						{
							list.AddRange(LightingLayoutOper.CalcLineLightingPosByCount(xyz2, xyz3, 2, true));
						}
					}
				}
			}
			return list;
		}

		private static ushort CalcLightingCounts(double dDistLane, bool bBeamCell)
		{
			ushort result = 0;
			dDistLane = dDistLane * 304.8 / 1000.0;
			GarageLaySettingAuxiliary garageLaySettingAuxiliary = new GarageLaySettingAuxiliary();
			LightingLayoutOper.m_strLightLayStyle = garageLaySettingAuxiliary.GetGarageLineInterfaceInfo().LightLayStyle;
			List<GarageLineSetting> list = new List<GarageLineSetting>();
			if (LightingLayoutOper.m_strLightLayStyle == "单")
			{
				list = garageLaySettingAuxiliary.GetSingleLayGarageLines();
			}
			else
			{
				list = garageLaySettingAuxiliary.GetDoubleLayGarageLines();
			}
			foreach (GarageLineSetting garageLineSetting in list)
			{
				if ((string.IsNullOrEmpty(garageLineSetting.Max) && dDistLane > Convert.ToDouble(garageLineSetting.Min)) || (string.IsNullOrEmpty(garageLineSetting.Max.Trim()) && dDistLane > Convert.ToDouble(garageLineSetting.Min)))
				{
					return Convert.ToUInt16(garageLineSetting.LightCount.ToString());
				}
				if (dDistLane > Convert.ToDouble(garageLineSetting.Min) && dDistLane <= Convert.ToDouble(garageLineSetting.Max))
				{
					return Convert.ToUInt16(garageLineSetting.LightCount.ToString());
				}
			}
			return result;
		}

		private static double m_dEpsilonDistFeet = Common.mmToFeet(1500.0);

		private static ushort m_nBeamCellCount = 3;

		private static ushort m_nFlatPlateFloorCount = 3;

		private static ushort m_nMaxCount = 4;

		public static string m_strLightLayStyle = "单";

		private static double[] m_arDist = new double[]
		{
			LightingLayoutOper.m_dEpsilonDistFeet,
			Common.mmToFeet(5300.0),
			Common.mmToFeet(7800.0),
			Common.mmToFeet(8400.0)
		};

		private static ushort[] m_arBeamCellCount = new ushort[]
		{
			1,
			2,
			LightingLayoutOper.m_nBeamCellCount,
			LightingLayoutOper.m_nMaxCount
		};

		private static ushort[] m_arFlatPlateFloorCount = new ushort[]
		{
			1,
			2,
			LightingLayoutOper.m_nFlatPlateFloorCount,
			LightingLayoutOper.m_nMaxCount
		};

		public class ComparableLine
		{
			public ComparableLine(Line geLine)
			{
				this.m_geLine = geLine;
			}

			public override bool Equals(object obj)
			{
				LightingLayoutOper.ComparableLine comparableLine = obj as LightingLayoutOper.ComparableLine;
				if (comparableLine != null)
				{
					XYZ startPoint = comparableLine.StartPoint;
					XYZ endPoint = comparableLine.EndPoint;
					return this.StartPoint.IsAlmostEqualTo(startPoint) && this.EndPoint.IsAlmostEqualTo(endPoint);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return (int)this.StartPoint.DistanceTo(this.EndPoint);
			}

			public XYZ StartPoint
			{
				get
				{
					return this.GeLine.GetEndPoint(0);
				}
			}

			public XYZ EndPoint
			{
				get
				{
					return this.GeLine.GetEndPoint(1);
				}
			}

			public Line GeLine
			{
				get
				{
					return this.m_geLine;
				}
			}

			private Line m_geLine;
		}

		private class UtilityTools
		{
			public static string PointString(XYZ p)
			{
				return string.Format("({0},{1},{2})", LightingLayoutOper.UtilityTools.RealString(p.X), LightingLayoutOper.UtilityTools.RealString(p.Y), LightingLayoutOper.UtilityTools.RealString(p.Z));
			}

			public static string RealString(double a)
			{
				return a.ToString("0.##");
			}
		}

		private class XyzEqualityComparer : IEqualityComparer<XYZ>
		{
			public XyzEqualityComparer(double eps)
			{
				this._eps = eps;
			}

			public bool Equals(XYZ p, XYZ q)
			{
				return this._eps > p.DistanceTo(q);
			}

			public int GetHashCode(XYZ p)
			{
				return LightingLayoutOper.UtilityTools.PointString(p).GetHashCode();
			}

			private double _eps;
		}

		public class LightingInfo : XYZ
		{
			public LightingInfo(XYZ pt, double dAng) : base(pt.X, pt.Y, pt.Z)
			{
				this.Angle = dAng;
			}

			public double Angle { get; set; }
		}
	}
}
